package com.itheima.rabbitmq.simple;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeoutException;

/**
 * @author : [chenxys]
 * @version : [v1.0]
 * @Description : 简单模式-消息的消费者
 * @createTime : [2022/6/22 18:50]
 */
public class Consumer {

    /**
     * 队列名称
     * QUEUE_NAME
     */
    public static final String QUEUE_NAME = "simple_queue";
    /**
     * 简单模式 消费者消费信息
     */
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1、创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();

        // 2、设置参数
        // 2.1、设置IP，默认为127.0.0.1
        factory.setHost("127.0.0.1");
        // 2.2、设置端口，默认为5672
        factory.setPort(5672);
        // 2.3、设置虚拟机,默认为/
        factory.setVirtualHost("/itcast");
        // 2.4、设置用户名,默认为guest
        factory.setUsername("heima");
        // 2.5、设置密码,默认为guest
        factory.setPassword("heima");

        // 3、创建连接 Connection
        Connection connection = factory.newConnection();

        // 4、创建channel
        Channel channel = connection.createChannel();

        // 5、创建队列
        /* queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
         *                       队列名称       是否持久化          是否独占本次连接    是否在不使用的时候自动删除队列         队列其它参数
         * 1、queue：队列名称
         * 2、durable：是否持久化[当mq重启后,仍然存在]
         * 3、exclusive：一般设置为 false
         *       * 是否独占：只能有一个消费者监听该条队列
         *       * 当Connection关闭时，是否删除队列
         * 4、autoDelete：是否自动删除。当没有Consumer时,自动删除
         * 5、arguments：队列其它参数
         * */
        //如果没有一个名为QUEUE_NAME的队列,则会自动创建该队列,反之则不会
        channel.queueDeclare(QUEUE_NAME, true, false, false, null);

        // 创建消费者；并设置消息处理
        DefaultConsumer consumer = new DefaultConsumer(channel){
           /**
            * 设置消息处理 回掉方法,当收到消息后会自动执行该方法
            * @author chenxys
            * @param consumerTag 消息标签，在channel.basicConsume时候可以指定
            * @param envelope 消息包的内容，可从中获取消息id，消息routingkey，交换机，消息和重传标志(收到消息失败后是否需要重新发送)
            * @param properties 属性[配置]信息
            * @param body 消息
            */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                //路由key
                System.out.println("路由key为:" + envelope.getRoutingKey());
                //交换机
                System.out.println("交换机:" + envelope.getExchange());
                //消息ID
                System.out.println("消息ID:" + envelope.getDeliveryTag());
                //收到的消息
                System.out.println("接收到的消息为:" + new String(body, StandardCharsets.UTF_8));
            }
        };

        // 监听消息
        /*basicConsume(String queue, boolean autoAck, Consumer callback)
        * 1、queue：队列名称
        * 2、autoAck：是否自动确认，
        *       * 设置为true为表示消息接收到自动向mq回复接收到了，mq接收到回复会删除消息，
        *       * 设置为false则需要手动确认
        * 3、callback：消息接收到后回调
        * */
        channel.basicConsume(QUEUE_NAME,true,consumer);

        // 消费者不应该关闭 应该一直监听
        /*channel.close();
        connection.close();*/
    }
}
